#if !defined(UNICODE) || !defined(_UNICODE)
#define UNICODE
#define _UNICODE
#endif

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // XP is the minimum
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include "Console.h"

int main()
{
	// get a handle to the built in console
	Con::Handle original = Con::GetOriginal();
	if(original) // this will be false for a windowed application
	{
		original->send_to_back();
		original << "Printing hello to original console\n";
		original->bring_to_top();
	}
	std::cout << "Printing hello to original console again\n";
	// creates a new console
	Con::Handle second;
	if(Con::Create(second))
	{
		second->bring_to_top();
		// write a message to it
		second << "Printing to second, please input an int\n";
		// grab an int from it
		int test = 0;
		second >> test;
		// echo the int
		second << "You entered " << test << '\n';
		// create a third
		Con::Handle third;
		if(Con::Create(third))
		{
			third->bring_to_top();
			// print a messgae
			third << "Enter a series of ints\n";
			std::vector<int> intVec;
			// grab a bunch of ints
			// the handle needs derefencing to grab the istream from a handle
			std::copy(std::istream_iterator<int>(*third), std::istream_iterator<int>(), std::back_inserter(intVec));
			// echo them out to second
			second->bring_to_top();
			second << "Some ints were read in on third, they were:\n";
			// make_ostream_iterator is required in order to see the results on second 
			// the copy operation will work with std::ostream_iterator but
			// flush will need to be called on the console handle to make them visible
			//
			// the commented line below is equivalent to the two below it
			// std::copy(intVec.begin(), intVec.end(), make_ostream_iterator<int>(second, "\n"));
			std::copy(intVec.begin(), intVec.end(), std::ostream_iterator<int>(*second, "\n"));
			second->flush();
			// simulate losing the reference to the second console
			// this will close the console window
			second.reset();
			third->bring_to_top();
			// do the same with third
			third << "Second destroyed, killing third\n";
			third.reset();
		}
		if(original)
		{
			original->bring_to_top();
			// losing a reference to original doesn't destroy the console provided by windows
			original << "Printing to first\n";
		}
	}
    return 0;
}